package com.example.nowcodercommunity.service;

import com.example.nowcodercommunity.dao.LoginTicketMapper;
import com.example.nowcodercommunity.dao.UserMapper;
import com.example.nowcodercommunity.entity.LoginTicket;
import com.example.nowcodercommunity.entity.User;
import com.example.nowcodercommunity.util.CommunityUtil;
import com.example.nowcodercommunity.util.MailClient;
import com.example.nowcodercommunity.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.util.StringUtils;


import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class UserService implements CommunityConstant{

    @Autowired
    private UserMapper mapper;

    @Autowired
    private MailClient mailClient;

    @Autowired
    private TemplateEngine engine;

    @Autowired
    private RedisTemplate redisTemplate;

//    @Autowired
//    private LoginTicketMapper loginMapper;

    @Value("${community.path.domain}")
    private String domain;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    public User findUserById(int id){
        User userFromCache = getUserFromCache(id);
        if(userFromCache == null){
            userFromCache = initUser(id);
        }
        return userFromCache;
    }

    public User findUserByName(String name){
        return mapper.selectByName(name);
    }

    public LoginTicket findTicketByTicket(String ticket){
        String ticketKey = RedisKeyUtil.getTicketKey(ticket);
        return (LoginTicket) redisTemplate.opsForValue().get(ticketKey);
    }

    /**
     * 用户注册方法
     * @param user
     * @return
     */
    public Map<String,Object> register(User user){
        Map<String,Object> map = new HashMap<>();

        if(user==null){
            throw new IllegalArgumentException("参数不能为空");
        }
        if(StringUtils.isEmpty(user.getName())){
            map.put("usernameMsg","用户名不能为空");
        }
        if(StringUtils.isEmpty(user.getPassword())){
            map.put("passwordMsg","密码不能为空");
        }
        if(StringUtils.isEmpty(user.getEmail())){
            map.put("mailMsg","注册邮箱不能为空");
        }

        User u = mapper.selectByName(user.getName());
        if(u!=null){
            map.put("usernameMsg","该账户已存在");
        }
        u = mapper.selectByEmail(user.getEmail());
        if(u!=null){
            map.put("mailMsg","该邮箱已被注册");
        }

        if(!map.isEmpty()){
            return map;
        }

        user.setSalt(CommunityUtil.generateUUID().substring(0,5));
        user.setPassword(CommunityUtil.md5(user.getPassword()+user.getSalt()));
        user.setType(0);
        user.setStatus(0);
        user.setActionCode(CommunityUtil.generateUUID());
        user.setHeader(String.format("http://images.nowcoder.com/head/%dt.png",new Random().nextInt(1000)));

        user.setCreateTime(new Date());

        mapper.insertUser(user);

        // 发送激活邮件
        Context context = new Context();
        context.setVariable("email",user.getEmail());
        String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActionCode();
        context.setVariable("url",url);
        String content = engine.process("/mail/activation",context);
        mailClient.sendMail(user.getEmail(),"NowCoder网站激活账号",content);

        return map;
    }

    /**
     * 用户激活方法
     */
    public int activation(int Id,String code){
        User user = mapper.selectById(Id);
        if(user.getStatus()==1){
            return ACTIVATION_REPEAT;
        } else if (user.getActionCode().equals(code)) {
            mapper.updateStatus(Id,1);
            cleanCache(Id);
            return ACTIVATION_SUCCESS;
        }else{
            return ACTIVATION_FAILURE;
        }
    }

    /**
     * 用户登录方法
     */
    public Map<String, Object> Login(String username,String password,int expireSeconds){
        Map<String, Object> map = new HashMap<>();

        if(StringUtils.isEmpty(username)){
            map.put("usernameMsg","账号不能为空！");
            return map;
        }
        if(StringUtils.isEmpty(password)){
            map.put("passwordMsg","密码不能为空！");
            return map;
        }

        User user = mapper.selectByName(username);

        if(user==null){
            map.put("usernameMsg","该账号不存在，请检查用户名！");
            return map;
        }
        if(user.getStatus()==0){
            map.put("usernameMsg","该账号未激活，请先激活账号！");
            return map;
        }
        if(!user.getPassword().equals(CommunityUtil.md5(password+user.getSalt()))){
            map.put("passwordMsg","密码错误，请重试！");
            return map;
        }

        LoginTicket ticket = new LoginTicket();
        ticket.setUserId(user.getId());
        ticket.setTicket(CommunityUtil.generateUUID());
        ticket.setStatus(0);
        ticket.setExpired(new Date(System.currentTimeMillis() + expireSeconds * 1000L));

        String ticketKey = RedisKeyUtil.getTicketKey(ticket.getTicket());
        redisTemplate.opsForValue().set(ticketKey, ticket);
        map.put("ticket", ticket);
//        if(loginMapper.insertLoginTicket(ticket)>0){
//            map.put("ticket",ticket);
//        }

        return map;
    }

    /**
     * 修改用户头像
     * @param id
     * @param header
     * @return
     */
    public int updateUserHeader(int id,String header){
        cleanCache(id);
        return mapper.updateHeader(id, header);
    }

    /**
     * 修改用户密码
     * @param id
     * @param password
     * @return
     */
    public int updateUserPassword(int id,String password){
        User user = findUserById(id);
        password = CommunityUtil.md5(password+user.getSalt());
        cleanCache(id);
        return mapper.updatePassword(id,password);
    }

    /**
     * 更新登录凭证
     * @param ticket
     * @param status
     */
    public void updateTicketStatus(String ticket,int status){
        String ticketKey = RedisKeyUtil.getTicketKey(ticket);
        LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(ticketKey);
        loginTicket.setStatus(status);
        redisTemplate.opsForValue().set(ticketKey, loginTicket);
    }

    /**
     * 从Redis缓存中取数据
     * @param userId
     * @return
     */
    private User getUserFromCache(int userId){
        String userKey = RedisKeyUtil.getUserKey(userId);
        return (User) redisTemplate.opsForValue().get(userKey);
    }

    /**
     * 从数据库中初始化缓存数据
     * 用于取不到缓存时使用
     * @param userId
     * @return
     */
    private User initUser(int userId){
        User user = mapper.selectById(userId);
        String userKey = RedisKeyUtil.getUserKey(userId);
        redisTemplate.opsForValue().set(userKey, user, 3600, TimeUnit.SECONDS);
        return user;
    }

    /**
     * 清除缓存数据，用于退出或数据改变
     * @param userId
     */
    private void cleanCache(int userId){
        String userKey = RedisKeyUtil.getUserKey(userId);
        redisTemplate.delete(userKey);
    }
}
